import { Inject, Injectable, Request, Scope } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model, Types } from 'mongoose'
import { Question, QuestionDocument } from './question.schema'
import { Result } from 'src/utils/result'
import { FindAllQueryDto } from './dto/FindAllQueryDto'
import { formatDate } from 'src/utils'
import { REQUEST } from '@nestjs/core'
import { UserDto } from 'src/users/dto/UserDto'
import {
  Components,
  ComponentsDocument
} from 'src/components/components.schema'
import { QuestionDto } from './dto/QuestionDto'
import { ComponentsDto } from 'src/components/dto/ComponentsDto'
import { Answer, AnswerDocument } from 'src/answer/answer.schema'
import { AnswerDto } from 'src/answer/dto/AnswerDto'

interface RequestWithUser extends Request {
  user?: UserDto
}

@Injectable({ scope: Scope.REQUEST })
export class QuestionService {
  constructor(
    @InjectModel(Question.name)
    private readonly questionModel: Model<QuestionDocument>,

    @InjectModel(Components.name)
    private readonly componentsModel: Model<ComponentsDocument>,

    @InjectModel(Answer.name)
    private readonly answerModel: Model<AnswerDocument>,

    @Inject(REQUEST) private readonly request: RequestWithUser
  ) {}

  /**
   * 查询所有问题
   * @param queryDto
   * @returns
   */
  async findAll(queryDto: FindAllQueryDto) {
    // 处理分页参数
    const pageNum = Math.max(Number(queryDto.pageNum) || 1, 1)
    const pageSize = Math.max(Number(queryDto.pageSize) || 10, 1)

    // 构建查询条件
    const query: Record<string, any> = {
      isDelete: queryDto.isDelete === '1' ? 1 : 0
    }

    if (queryDto.title?.trim()) {
      query.title = new RegExp(queryDto.title.trim(), 'i')
    }

    if (queryDto.isStar !== undefined) {
      query.star = { $eq: queryDto.isStar === 'true' }
    }

    // 并行执行查询和总数统计
    const [list, total] = await Promise.all([
      this.questionModel
        .find(query)
        .skip((pageNum - 1) * pageSize)
        .limit(pageSize),
      this.questionModel.countDocuments(query)
    ])

    return Result.success({
      list,
      total
    })
  }

  /**
   * 添加问卷
   * @param question
   * @returns
   */
  async addQuestion(question: QuestionDto): Promise<Result<null>> {
    try {
      if (!question.componentsList || question.componentsList.length === 0) {
        return Result.error().setMsg('问卷至少包含一个组件')
      }

      if (!this.request.user?._id) {
        return Result.error().setMsg('用户未登录')
      }

      const newQuestion = {
        userId: this.request.user._id,
        createTime: formatDate(),
        isDelete: 0,
        title: question.title,
        publish: question.publish,
        star: question.star,
        description: question.description,
        jsCode: question.jsCode,
        cssCode: question.cssCode
      }

      const result = (await this.questionModel.create(newQuestion)) as {
        _id: string
      }

      // 拿到新增的问卷的id
      if (result._id) {
        // 组装组件列表
        const componentsList = question.componentsList.map(comp => {
          const newComp = { ...comp }
          if (newComp._id) {
            delete newComp._id
          } // 删除组件列表中的_id
          return {
            ...newComp,
            questionId: result._id.toString()
          }
        })

        // 组件列表插入到数据库
        await this.componentsModel.insertMany(componentsList)
      }
      return Result.success(null)
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }

  /**
   * 获取问卷信息
   * @param id
   * @returns
   */
  async getQuestionById(id: string): Promise<Result<QuestionDto | null>> {
    // 并行查询问卷基本信息和组件列表
    const [questionDoc, componentsList] = await Promise.all([
      this.questionModel.findById(id).lean<QuestionDto>(),
      this.componentsModel.find({ questionId: id }).lean<ComponentsDto[]>()
    ])

    if (!questionDoc) {
      return Result.success(null)
    }

    const questionDto: QuestionDto = {
      ...questionDoc,
      componentsList
    }

    return Result.success(questionDto)
  }

  /**
   * 更新问卷
   * @param updateQuestionDto
   * @returns
   */
  async updateQuestion(
    updateQuestionDto: QuestionDto
  ): Promise<Result<QuestionDto | null>> {
    try {
      const {
        _id,
        title,
        publish,
        star,
        isDelete,
        description,
        jsCode,
        cssCode,
        componentsList
      } = updateQuestionDto
      const updateFields: Partial<Question> = {}
      if (title !== undefined) updateFields.title = title
      if (publish !== undefined) updateFields.publish = publish
      if (star !== undefined) updateFields.star = star
      if (isDelete !== undefined) updateFields.isDelete = isDelete
      if (description !== undefined) updateFields.description = description
      if (jsCode !== undefined) updateFields.jsCode = jsCode
      if (cssCode !== undefined) updateFields.cssCode = cssCode

      try {
        // 根据id更新
        await this.questionModel.updateOne(
          { _id: _id },
          {
            $set: updateFields
          }
        )

        // 仅当 componentsList 存在时才更新组件数据
        if (componentsList !== undefined) {
          // 删除旧组件
          await this.componentsModel.deleteMany({ questionId: _id })

          // 插入新组件
          const newComponents = componentsList.map(comp => {
            const { _id, ...compWithoutId } = comp
            return {
              ...compWithoutId,
              questionId: updateQuestionDto._id!.toString()
            }
          })

          await this.componentsModel.insertMany(newComponents)
        }

        // 吧更新后的组件信息返回
        const updatedQuestion = await this.questionModel
          .findById(_id)
          .lean<QuestionDto>()

        return Result.success(updatedQuestion)
      } catch (error: any) {
        return Result.error().setMsg(error)
      }
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }

  /**
   * 删除问卷
   * @param id
   * @returns
   */
  async deleteQuestion(id: string): Promise<Result<null>> {
    try {
      await this.questionModel.updateOne(
        { _id: id },
        {
          $set: { isDelete: 1 }
        }
      )
      return Result.success(null)
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }

  /**
   * 批量还原
   */
  async restoreQuestion(ids: string[]): Promise<Result<null>> {
    try {
      await this.questionModel.updateMany(
        { _id: { $in: ids } },
        { $set: { isDelete: 0 } }
      )
      return Result.success(null)
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }

  /**
   * 彻底删除
   */
  async deleteQuestionCompletely(ids: string[]): Promise<Result<null>> {
    try {
      await this.questionModel.deleteMany({ _id: { $in: ids } })
      return Result.success(null)
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }

  /**
   * 根据问卷id获取答卷列表
   */
  async getAnswerList(
    questionId: string,
    pageNum: string,
    pageSize: string
  ): Promise<Result> {
    try {
      if (!questionId) {
        return Result.error().setMsg('Question ID is required')
      }

      try {
        const query = { questionId: questionId }
        const skip = pageNum
          ? (parseInt(pageNum, 10) - 1) * parseInt(pageSize, 10)
          : 0
        const limit = parseInt(pageSize, 10) // 每页文档数量

        // 从答案表中分页获取数据
        const total = await this.answerModel.countDocuments(query) // 获取总记录数

        const answers = await this.answerModel
          .find(query)
          .skip(skip)
          .limit(limit)
          .lean<Answer[]>()

        const rows = answers.map(answer => {
          const { _id, questionId, answers } = answer
          return {
            _id,
            questionId,
            ...answers
          }
        })

        return Result.success({
          total, // 总记录数
          pageNum: parseInt(pageNum, 10), // 当前页码
          pageSize: limit, // 每页数量
          rows // 当前页数据
        })
      } catch (error) {
        return Result.error().setMsg(JSON.stringify(error))
      }
    } catch (error: any) {
      return Result.error().setMsg(JSON.stringify(error))
    }
  }

  /**
   * 查询指定字段的统计数据
   * @param questionId 文件id
   * @param componentId 组件id
   * @param name 字段id
   * @returns
   */
  async getComponentStatistics(
    questionId: string,
    componentId: string,
    name: string
  ): Promise<Result<Array<{ value: string; count: number }>>> {
    try {
      // 1. 参数验证
      if (!questionId || !componentId) {
        return Result.error().setMsg(
          'Question ID and Component ID are required'
        )
      }

      // 1. 根据问卷ID获取组件列表
      const query = { questionId: questionId }
      const componentsList = await this.componentsModel
        .find(query)
        .lean<ComponentsDto[]>()

      // 2. 获取某个组件信息
      const componentInfo = componentsList.find(item =>
        new Types.ObjectId(item._id).equals(new Types.ObjectId(componentId))
      )
      if (!componentInfo) {
        return Result.error().setMsg('组件ID不存在')
      }

      // 3. 获取所有答卷
      const answers = await this.answerModel
        .find({ questionId })
        .lean<AnswerDto[]>()

      // 4. 统计答案
      const stat = new Map<string, number>()

      for (const answer of answers) {
        const componentAnswer = answer.answers[name]
        if (!componentAnswer) continue

        if (componentInfo.type === 'QuestionCheckbox') {
          // 多选题处理
          const options = componentAnswer.split(',')
          options.forEach(option => {
            const trimmed = option.trim()
            stat.set(trimmed, (stat.get(trimmed) || 0) + 1)
          })
        } else if (componentInfo.type === 'QuestionRadio') {
          // 单选题处理
          stat.set(componentAnswer, (stat.get(componentAnswer) || 0) + 1)
        }
      }

      // 5. 格式化结果
      const result = Array.from(stat.entries()).map(([value, count]) => ({
        value,
        count
      }))

      return Result.success(result)
    } catch (error) {
      return Result.error().setMsg(JSON.stringify(error))
    }
  }

  /**
   * 获取已创建的问卷数量，已发布的数量，收到的答卷数
   */

  async getQuestionStatistics(): Promise<Result<any>> {
    try {
      const [questionTotal, published, answered] = await Promise.all([
        this.questionModel.countDocuments({ isDelete: 0 }),
        this.questionModel.countDocuments({ publish: true, isDelete: 0 }),
        this.answerModel.countDocuments()
      ])
      return Result.success({ questionTotal, published, answered })
    } catch (error: any) {
      return Result.error().setMsg(error)
    }
  }
}
